package com.allm.ai.api.controller;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.allm.ai.common.dto.ApiRequest;
import com.allm.ai.common.dto.StreamingOutput;
import com.allm.ai.common.entity.AiModel;
import com.allm.ai.common.entity.ConversationMessage;
import com.allm.ai.common.entity.ConversationRound;
import com.allm.ai.common.factory.AiModelStrategyFactory;
import com.allm.ai.common.service.AiModelService;
import com.allm.ai.common.service.ConversationMessageService;
import com.allm.ai.common.service.ConversationRoundService;
import com.allm.ai.common.strategy.AiModelStrategy;
import com.allm.ai.common.util.IdUtils;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Flux;

/**
 * 聊天对话API控制器
 * 提供基于RAG的智能对话功能
 * 
 * @author com.enplatform
 */
@Slf4j
@RestController
@RequestMapping("/chat")
@EnableAsync
@CrossOrigin(origins = "*", allowedHeaders = "*", methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE, RequestMethod.OPTIONS}, allowCredentials = "false")
@RequiredArgsConstructor
public class ChatController {

    private final AiModelService aiModelService;
    private final AiModelStrategyFactory strategyFactory;
    private final ConversationMessageService messageService;
    private final ConversationRoundService roundService;

    
     /**
     * 创建轮次占位符接口 - 页面先提交轮次请求
     */
    @PostMapping("/create-round")
    public ResponseEntity<Map<String, Object>> createRound(@RequestBody Map<String, Object> request) {
        try {
            // 参数验证
            String conversationId = (String) request.get("conversationId");
            String userId = (String) request.get("userId");
            String question = (String) request.get("question");
            @SuppressWarnings("unchecked")
            List<Integer> modelIds = (List<Integer>) request.get("modelIds");
            
            if (conversationId == null || conversationId.trim().isEmpty()) {
                return ResponseEntity.badRequest()
                    .body(Map.of("success", false, "error", "ConversationId is required"));
            }
            
            if (userId == null || userId.trim().isEmpty()) {
                return ResponseEntity.badRequest()
                    .body(Map.of("success", false, "error", "UserId is required"));
            }
            
            if (question == null || question.trim().isEmpty()) {
                return ResponseEntity.badRequest()
                    .body(Map.of("success", false, "error", "Question is required"));
            }
            
            if (modelIds == null || modelIds.isEmpty()) {
                return ResponseEntity.badRequest()
                    .body(Map.of("success", false, "error", "ModelIds is required"));
            }
            
            // 类型转换：确保modelIds是Long类型
            List<Long> longModelIds = modelIds.stream()
                .map(id -> Long.valueOf(id.toString()))
                .collect(Collectors.toList());
            
            // 创建轮次占位符（保持最简单）
            ConversationRound round = roundService.createRoundPlaceholder(conversationId, userId, question, longModelIds);
            
            return ResponseEntity.ok(Map.of(
                "success", true,
                "data", Map.of(
                    "roundNumber", round.getRoundNumber(),
                    "conversationId", conversationId,
                    "modelIds", longModelIds,
                    "isFirstRound", round.getIsFirstRound()
                )
            ));
            
        } catch (Exception e) {
            log.error("创建轮次占位符失败", e);
            return ResponseEntity.internalServerError()
                .body(Map.of("success", false, "error", "创建轮次占位符失败: " + e.getMessage()));
        }
    }

    /**
     * 流式智能问答接口 - 基于轮次的调用
     */
    @PostMapping(value = "/ask-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    @Transactional(readOnly = true)
    public Flux<ServerSentEvent<StreamingOutput>> askStream(@RequestBody Map<String, Object> request) {
        try {
            // 参数验证
            String conversationId = (String) request.get("conversationId");
            Integer roundNumber = (Integer) request.get("roundNumber");
            Long modelId = request.get("modelId") != null ? Long.valueOf(request.get("modelId").toString()) : null;
            Integer contextSize = (Integer) request.getOrDefault("contextSize", 5);
            
            if (conversationId == null || conversationId.trim().isEmpty()) {
                return Flux.just(ServerSentEvent.<StreamingOutput>builder()
                    .event("error")
                    .data(new StreamingOutput(StreamingOutput.ERROR, "ConversationId is required"))
                    .build());
            }
            
            if (roundNumber == null) {
                return Flux.just(ServerSentEvent.<StreamingOutput>builder()
                    .event("error")
                    .data(new StreamingOutput(StreamingOutput.ERROR, "RoundNumber is required"))
                    .build());
            }
            
            if (modelId == null) {
                return Flux.just(ServerSentEvent.<StreamingOutput>builder()
                    .event("error")
                    .data(new StreamingOutput(StreamingOutput.ERROR, "ModelId is required"))
                    .build());
            }
            
            // 在流式处理开始前，先获取所有需要的数据
            return Flux.defer(() -> {
                try {
                    // 获取指定的模型信息
                    Optional<AiModel> modelOpt = aiModelService.findById(modelId);
                    if (modelOpt.isEmpty()) {
                        return Flux.just(ServerSentEvent.<StreamingOutput>builder()
                            .event("error")
                            .data(new StreamingOutput(StreamingOutput.ERROR, "Model not found with id: " + modelId))
                            .build());
                    }
                    
                    AiModel model = modelOpt.get();
                    
                    // 获取轮次信息
                    Optional<ConversationRound> roundOpt = roundService.getRound(conversationId, roundNumber);
                    if (roundOpt.isEmpty()) {
                        return Flux.just(ServerSentEvent.<StreamingOutput>builder()
                            .event("error")
                            .data(new StreamingOutput(StreamingOutput.ERROR, "Round not found: " + roundNumber))
                            .build());
                    }
                    
                    ConversationRound round = roundOpt.get();
                    
                    // 保存用户问题消息
                    int messageOrder = messageService.getNextMessageOrder(conversationId);
                    String modelConversationId = IdUtils.generateModelConversationId(conversationId, modelId);
                    messageService.saveUserMessage(conversationId, modelConversationId, modelId, 
                                                 round.getQuestion(), messageOrder, round.getRoundNumber());
                    
                    // 构建API请求时使用实际的历史消息
                    List<Map<String, Object>> historyMessages = buildHistoryMessages(messageService.getConversationMessages(conversationId));
                    
                    ApiRequest apiRequest = ApiRequest.builder()
                        .model(model.getName())
                        .messages(buildMessages(round.getQuestion(), historyMessages, contextSize))
                        .temperature(0.7)
                        .maxTokens(2000)
                        .conversationId(modelConversationId)
                        .history(historyMessages)
                        .contextSize(contextSize)
                        .build();
                    
                    // 使用策略工厂获取对应的策略
                    AiModelStrategy strategy = strategyFactory.getStrategy(model.getServiceProvider());
                    
                    // 检查策略是否支持流式输出
                    if (!strategy.supportsStreaming()) {
                        return Flux.just(ServerSentEvent.<StreamingOutput>builder()
                            .event("error")
                            .data(new StreamingOutput(StreamingOutput.ERROR, String.format("模型 '%s' (提供商: %s) 不支持流式输出，请使用支持流式输出的模型", 
                            model.getName(), model.getServiceProvider())))
                            .build());
                    }

                    // 调用流式 API
                    return strategy.callApiStream(model, apiRequest)
                        .map(chunk -> ServerSentEvent.<StreamingOutput>builder()
                            .data(chunk)
                            .build())
                        .doOnNext(event -> log.debug("发送流式事件: {}", event.data()))
                        .concatWith(Flux.just(ServerSentEvent.<StreamingOutput>builder()
                            .event("complete")
                            .data(new StreamingOutput(StreamingOutput.DONE, ""))
                            .build()))
                        .doOnComplete(() -> {
                            log.info("流式聊天完成，主conversationId: {}, 模型conversationId: {}, roundNumber: {}", 
                                    conversationId, modelConversationId, roundNumber);
                        })
                        .onErrorResume(error -> {
                            log.error("流式聊天失败", error);
                            return Flux.just(ServerSentEvent.<StreamingOutput>builder()
                                .event("error")
                                .data(new StreamingOutput(StreamingOutput.ERROR, "流式调用失败: " + error.getMessage()))
                                .build());
                        });
                    
                } catch (Exception e) {
                    log.error("流式处理失败", e);
                    return Flux.just(ServerSentEvent.<StreamingOutput>builder()
                        .event("error")
                        .data(new StreamingOutput(StreamingOutput.ERROR, "处理失败: " + e.getMessage()))
                        .build());
                }
            });
            
        } catch (Exception e) {
            log.error("askStream 方法执行失败", e);
            return Flux.just(ServerSentEvent.<StreamingOutput>builder()
                .event("error")
                .data(new StreamingOutput(StreamingOutput.ERROR, "系统错误: " + e.getMessage()))
                .build());
        }
    }

    /**
     * 构建消息格式
     */
    private List<Map<String, Object>> buildMessages(String question, List<Map<String, Object>> history, Integer contextSize) {
        List<Map<String, Object>> messages = new ArrayList<>();
        
        // 添加历史对话（限制上下文大小）
        if (history != null && !history.isEmpty()) {
            int startIndex = Math.max(0, history.size() - contextSize);
            for (int i = startIndex; i < history.size(); i++) {
                Map<String, Object> msg = history.get(i);
                if (msg.containsKey("role") && msg.containsKey("content")) {
                    messages.add(msg);
                }
            }
        }
        
        // 添加当前问题
        Map<String, Object> currentMessage = new HashMap<>();
        currentMessage.put("role", "user");
        currentMessage.put("content", question);
        messages.add(currentMessage);
        
        return messages;
    }

    /**
     * 获取用户历史记录，用于保存
     */
    @GetMapping("/history")
    public ResponseEntity<Map<String, Object>> getConversationHistory(@RequestParam String userId) {
        try {
            // 获取用户的所有对话ID（去重，已在数据库中排序）
            List<String> conversationIds = roundService.getUserConversationIds(userId);
            
            List<Map<String, Object>> historyList = new ArrayList<>();
            
            for (String conversationId : conversationIds) {
                // 获取该对话的第一轮记录（用于显示问题）
                Optional<ConversationRound> firstRound = roundService.getConversationSummary(conversationId);
                if (firstRound.isPresent()) {
                    ConversationRound round = firstRound.get();
                    
                    // 从轮次的modelIds字段获取模型信息
                    String modelIdsStr = round.getModelIds();
                    List<Long> modelIds = new ArrayList<>();
                    if (modelIdsStr != null && !modelIdsStr.trim().isEmpty()) {
                        modelIds = List.of(modelIdsStr.split(","))
                            .stream()
                            .map(String::trim)
                            .filter(s -> !s.isEmpty())
                            .map(Long::valueOf)
                            .collect(Collectors.toList());
                    }
                    
                    Map<String, Object> item = new HashMap<>();
                    item.put("conversationId", conversationId);
                    item.put("question", round.getQuestion());
                    item.put("timestamp", round.getLastMessageAt());
                    item.put("modelCount", modelIds.size());
                    
                    // 获取该对话的模型信息
                    List<Map<String, Object>> models = new ArrayList<>();
                    for (Long modelId : modelIds) {
                        Optional<AiModel> modelOpt = aiModelService.findById(modelId);
                        if (modelOpt.isPresent()) {
                            AiModel model = modelOpt.get();
                            models.add(Map.of(
                                "id", model.getId(),
                                "name", model.getDisplayName()
                            ));
                        }
                    }
                    item.put("models", models);
                    
                    historyList.add(item);
                }
            }
            
            return ResponseEntity.ok(Map.of(
                "success", true,
                "data", historyList
            ));
            
        } catch (Exception e) {
            log.error("获取历史记录失败", e);
            return ResponseEntity.ok(Map.of(
                "success", false,
                "message", "获取历史记录失败: " + e.getMessage()
            ));
        }
    }

    /**
     * 获取对话详情 - 基于轮次构建，每轮对话的模型信息可能不同
     */
    @GetMapping("/conversation/{conversationId}")
    public ResponseEntity<Map<String, Object>> getConversationDetails(@PathVariable String conversationId) {
        try {
            // 获取对话的轮次信息
            List<ConversationRound> rounds = roundService.getConversationRounds(conversationId);
            if (rounds.isEmpty()) {
                return ResponseEntity.ok(Map.of(
                    "success", false,
                    "message", "对话不存在"
                ));
            }
            
            // 构建所有可能的模型信息
            Map<Long, AiModel> modelMap = new HashMap<>();
            List<AiModel> models = aiModelService.findActiveModels();
            for (AiModel model : models) {
                modelMap.put(model.getId(), model);
            }
            
            // 基于轮次构建聊天历史（每轮都有自己的模型信息）
            List<Map<String, Object>> chatHistory = buildChatHistoryFromRounds(rounds, modelMap);
            
            Map<String, Object> response = new HashMap<>();
            response.put("conversationId", conversationId);
            response.put("messages", chatHistory);
            
            return ResponseEntity.ok(Map.of(
                "success", true,
                "data", response
            ));
            
        } catch (Exception e) {
            log.error("获取对话详情失败", e);
            return ResponseEntity.ok(Map.of(
                "success", false,
                "message", "获取对话详情失败: " + e.getMessage()
            ));
        }
    }

     /**
     * 基于轮次构建聊天历史 - 每轮对话的模型信息可能不同
     */
    private List<Map<String, Object>> buildChatHistoryFromRounds(List<ConversationRound> rounds, 
                                                               Map<Long, AiModel> modelMap) {
        List<Map<String, Object>> chatHistory = new ArrayList<>();
        
        for (ConversationRound round : rounds) {
            // 解析该轮次的模型ID列表
            String modelIdsStr = round.getModelIds();
            List<Long> roundModelIds = new ArrayList<>();
            if (modelIdsStr != null && !modelIdsStr.trim().isEmpty()) {
                roundModelIds = List.of(modelIdsStr.split(","))
                    .stream()
                    .map(String::trim)
                    .filter(s -> !s.isEmpty())
                    .map(Long::valueOf)
                    .collect(Collectors.toList());
            }
            
            // 获取该轮次的所有消息
            List<ConversationMessage> roundMessages = messageService.getRoundMessages(
                round.getConversationId(), round.getRoundNumber());
            
            // 构建聊天历史项
            Map<String, Object> chatItem = new HashMap<>();
            chatItem.put("question", round.getQuestion());
            chatItem.put("timestamp", round.getCreatedAt());
            chatItem.put("roundNumber", round.getRoundNumber());
            chatItem.put("isFirstRound", round.getIsFirstRound());
            
            // 为该轮次的每个模型创建响应结构
            Map<String, Map<String, Object>> responsesByModel = new HashMap<>();
            
            for (Long modelId : roundModelIds) {
                AiModel model = modelMap.get(modelId);
                if (model != null) {
                    String modelKey = model.getName();
                    
                    // 从消息中查找该模型的响应
                    Optional<ConversationMessage> assistantMessageOpt = roundMessages.stream()
                        .filter(msg -> msg.getRole() == ConversationMessage.MessageRole.ASSISTANT 
                                     && msg.getModelId().equals(modelId))
                        .findFirst();
                    
                    Map<String, Object> modelResponse = new HashMap<>();
                    
                    if (assistantMessageOpt.isPresent()) {
                        // 有实际的响应消息
                        ConversationMessage assistantMessage = assistantMessageOpt.get();
                        modelResponse.put("content", assistantMessage.getContent() != null ? assistantMessage.getContent() : "");
                        modelResponse.put("thinkingContent", assistantMessage.getThinkingContent() != null ? assistantMessage.getThinkingContent() : "");
                        modelResponse.put("timestamp", assistantMessage.getCreatedAt());
                        modelResponse.put("status", "success");
                    } else {
                        // 没有响应消息，使用占位符
                        modelResponse.put("content", "");
                        modelResponse.put("thinkingContent", "");
                        modelResponse.put("timestamp", round.getCreatedAt());
                        modelResponse.put("status", "pending");
                    }
                    
                    modelResponse.put("modelId", modelId);
                    modelResponse.put("modelName", model.getDisplayName());
                    
                    responsesByModel.put(modelKey, modelResponse);
                }
            }
            
            chatItem.put("responses", responsesByModel);
            chatItem.put("modelIds", roundModelIds); // 添加该轮次的模型ID列表
            chatHistory.add(chatItem);
        }
        
        // 按时间排序
        chatHistory.sort((a, b) -> {
            LocalDateTime dateA = (LocalDateTime) a.get("timestamp");
            LocalDateTime dateB = (LocalDateTime) b.get("timestamp");
            return dateA.compareTo(dateB);
        });
        
        return chatHistory;
    }


    /**
     * 删除历史记录
     */
    @DeleteMapping("/history/{conversationId}")
    public ResponseEntity<Map<String, Object>> deleteHistory(@PathVariable String conversationId) {
        try {
            roundService.deactivateConversationRounds(conversationId);
            
            return ResponseEntity.ok(Map.of(
                "success", true,
                "message", "删除成功"
            ));
            
        } catch (Exception e) {
            log.error("删除历史记录失败", e);
            return ResponseEntity.ok(Map.of(
                "success", false,
                "message", "删除失败: " + e.getMessage()
            ));
        }
    }

    /**
     * 从历史消息构建API请求的消息列表
     */
    private List<Map<String, Object>> buildHistoryMessages(List<ConversationMessage> messages) {
        List<Map<String, Object>> historyMessages = new ArrayList<>();
        for (ConversationMessage msg : messages) {
            Map<String, Object> historyItem = new HashMap<>();
            historyItem.put("role", msg.getRole().name()); // 转换为字符串
            historyItem.put("content", msg.getContent());
            historyItem.put("thinking_content", msg.getThinkingContent());
            historyItem.put("message_order", msg.getMessageOrder());
            historyItem.put("created_at", msg.getCreatedAt());
            historyMessages.add(historyItem);
        }
        return historyMessages;
    }

    @PostMapping("/save-response")
    public ResponseEntity<Map<String, Object>> saveResponse(@RequestBody Map<String, Object> request) {
        try {
            String conversationId = (String) request.get("conversationId");
            String modelKey = (String) request.get("modelKey");
            String content = (String) request.get("content");
            String thinking = (String) request.get("thinking");
            
            // 根据modelKey找到对应的模型ID
            Optional<AiModel> modelOpt = aiModelService.findByName(modelKey);
            if (modelOpt.isEmpty()) {
                return ResponseEntity.badRequest().body(Map.of("success", false, "message", "模型不存在"));
            }
            
            AiModel model = modelOpt.get();
            
            // 获取当前轮次编号
            Integer currentRoundNumber = roundService.getLatestRoundNumber(conversationId);
            
            // 获取下一个消息顺序
            int messageOrder = messageService.getNextMessageOrder(conversationId);
            
            // 生成模型对话ID
            String modelConversationId = IdUtils.generateModelConversationId(conversationId, model.getId());
            
            messageService.saveAssistantMessage(conversationId, modelConversationId, 
                                               model.getId(), content, thinking, 
                                               messageOrder, currentRoundNumber);
            
            return ResponseEntity.ok(Map.of("success", true));
            
        } catch (Exception e) {
            log.error("保存响应失败", e);
            return ResponseEntity.internalServerError().body(Map.of("success", false, "message", "保存失败"));
        }
    }

    /**
     * 获取对话轮次目录的接口
     */
    @GetMapping("/conversation/{conversationId}/rounds")
    public ResponseEntity<Map<String, Object>> getConversationRounds(@PathVariable String conversationId) {
        try {
            List<ConversationRound> rounds = roundService.getConversationRounds(conversationId);
            
            List<Map<String, Object>> roundsList = rounds.stream()
                .map(round -> {
                    Map<String, Object> item = new HashMap<>();
                    item.put("roundNumber", round.getRoundNumber());
                    item.put("question", round.getQuestion());
                    item.put("questionSummary", round.getQuestionSummary());
                    item.put("createdAt", round.getCreatedAt());
                    return item;
                })
                .collect(Collectors.toList());
            
            return ResponseEntity.ok(Map.of(
                "success", true,
                "data", roundsList
            ));
            
        } catch (Exception e) {
            log.error("获取对话轮次失败", e);
            return ResponseEntity.ok(Map.of(
                "success", false,
                "message", "获取对话轮次失败: " + e.getMessage()
            ));
        }
    }
}
